﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Configuration;
using Fast.Presentation.Print;
using Contract.Business.Process;
using Contract.Business.Entity;
using Contract.Business.Filter;

namespace Fast.Presentation.Bematech
{
    public class BematechPrinter : IPrinter
    {
        #region Funções Bematech 4200 USB
        [DllImport("MP2032.dll")] // Função utilizada para iniciar a porta da impressora
        public static extern int IniciaPorta(string porta);

        /// <summary>
        /// Imprimir
        /// </summary>
        /// <param name="texto">Texto a ser impresso</param>
        /// <returns></returns>
        [DllImport("MP2032.dll")]
        public static extern int BematechTX(string texto);

        [DllImport("MP2032.dll")]
        public static extern int ConfiguraModeloImpressora(int tipoImpressora);
        //0: MP-20 TH, MP-2000 CI ou MP-2000 TH 
        //1: MP-20 MI, MP-20 CI ou MP-20 S
        //2: Blocos térmicos (com comunicacao serial DTR/DSR)
        //3: Bloco 112 mm
        //4: ThermalKiosk
        //5: MP-4000 TH
        //7: MP-4200 TH

        /// <summary>
        /// Esta função aciona a guilhotina, contando o papel em modo parcial ou total.
        /// </summary>
        /// <param name="modo">0 (zero): Modo Parcial (Parcial Cut) ou 1 (um): Modo Total (Full Cut).</param>
        /// <returns>0 (zero): Erro de Comunicação ||| 1 (um): OK. ||| -2 (menos dois): Parâmetro Inválido.</returns>
        [DllImport("MP2032.dll")]
        public static extern int AcionaGuilhotina(int modo);

        /// <summary>
        /// Seleciona a largura da bitola do papel da impressora.
        /// </summary>
        /// <param name="modo">iWidth: Variável do tipo INTEIRA, indicando a bitola do papel em milímetros. Podendo ser: 48, 58, 76, 80 ou 112.</param>
        /// <returns>0 (zero): Erro de Comunicação ||| 1 (um): OK. ||| -4 (menos quatro): Parâmetro Inválido.</returns>
        /// Observação: A largura default utilizada pela DLL é de 48 mm, caso não se configure uma nova largura, a impressão do bitmap será limitada a esse valor.
        [DllImport("MP2032.dll")]
        public static extern int AjustaLarguraPapel(int width);

        /// <summary>
        ///  Esta função permite autenticar documentos com uma maior facilidade, sem a necessidade do aplicativo enviar os comandos de autenticação para a impressora. Basta passar o texto que deseja autenticar e o tempo de espera, definido em milissegundos.
        /// </summary>
        /// <param name="texto">STRING que será usada na autenticação</param>
        /// <param name="tempo">INTEIRO com o tempo de espera em milisegundos</param>
        /// <returns>1 (um) : Sucesso. A função foi executada sem problemas. ||| 0 (zero) : Time-Out. O documento não foi inserido no tempo determinado.</returns>
        [DllImport("MP2032.dll")]
        public static extern int AutenticaDoc(string texto, int tempo);

        /// <summary>
        ///  Esta função é utilizada no envio de comandos para a impressora, como por exemplo: comandos de Autenticação, comando para Acionamento de Gaveta, comandos para Habilitar Tabelas de Caracteres, etc.
        /// </summary>
        /// <param name="comando">STRING com o comando que deseja executar</param>
        /// <param name="tamanhoComando">INTEIRO com o tamanho do comando que será enviado</param>
        /// <returns>1 (um): Sucesso. A função foi executada sem problemas. ||| 0 (zero): Erro na comunicação.</returns>
        ///' Exemplo em Visual Basic
        ///' Comando para Acionar a Gaveta de Dinheiro
        ///sComando = chr( 27 ) + chr( 118 ) + chr( 140 )
        ///iRetorno = ComandoTX( sComando, Len( sComando )
        [DllImport("MP2032.dll")]
        public static extern int ComandoTX(string comando, int tamanhoComando);

        /// <summary>
        /// Esta função configura a quantidade de linhas impressas no extrato, antes de começar a espulsá-lo (eject). A quantidade de linhas pode variar de 1 a 150 linhas. O Default é 90 linhas.
        /// </summary>
        /// <param name="tamanho">INTEIRO com o tamanho do extrato.</param>
        /// <returns>0 (zero): Erro de Comunicação. ||| 1 (um): OK. ||| -2 (menos dois): Parâmetro Inválido.</returns>
        ///  Observação: Somente utilizada para os Blocos Impressores.
        [DllImport("MP2032.dll")]
        public static extern int ConfiguraTamanhoExtrato(int tamanho);

        /// <summary>
        /// Esta função configura o taxa de transmissão para a porta serial. Ela dever ser chamada ANTES da função IniciaPorta.
        /// </summary>
        /// <param name="taxaBps"> INTEIRO com a taxa em bps (bits por segundo). Esta taxa pode ser 9600 ou 115200.</param>
        [DllImport("MP2032.dll")]
        public static extern void ConfiguraTaxaSerial(int taxaBps);

        /// <summary>
        /// Esta função segura a execução do Aplicativo, até que todo o texto enviado seja impresso.
        /// </summary>
        /// <param name="modoEspera">INTEIRO com o modo de espera. 1 (um): Habilita ou 0 (zero): Desabilita</param>
        [DllImport("MP2032.dll")]
        public static extern void EsperaImpressao(int modoEspera);

        /// <summary>
        /// Esta função tem por objetivo fechar a porta de comunicação, liberando a porta para outras atividades.
        /// </summary>
        /// <returns>1 (um): Sucesso. A função foi executada sem problemas. ou 0 (zero): Erro ao fechar a porta de comunicação.</returns>
        /// Observação: A função FechaPorta() deve ser usada, somente na saída da Aplicação, ou seja, quando for encerrar o trabalho com a Impressora
        [DllImport("MP2032.dll")]
        public static extern int FechaPorta();

        /// <summary>
        /// Esta função tem por objetivo enviar textos para a impressora, com formatações, informadas pelos parâmetros.
        /// </summary>
        /// <param name="texto">Texto para imprimir</param>
        /// <param name="tipoLetra">1 = comprimido ou 2 = normal ou 3 = elite</param>
        /// <param name="italico">1 ativado ou 0 desativado</param>
        /// <param name="sublinhado">1 ativado ou 0 desativado</param>
        /// <param name="expandido">1 ativado ou 0 desativado</param>
        /// <param name="negrito">1 ativado ou 0 desativado</param>
        /// <returns>1 (um): Sucesso. A função foi executada sem problemas ou 0 (zero): Erro de comunicação física.</returns>
        [DllImport("MP2032.dll")]
        public static extern int FormataTX(string texto, int tipoLetra, int italico, int sublinhado, int expandido, int negrito);

        /// <summary>
        /// Esta função habilita ou desabilita o envio do caracter ETX (03h), que mantém a impressora ocupada até o término da impressão de todo o texto (string).
        /// </summary>
        /// <param name="habilitado">0 - desabilitado ou 1 - habilitado</param>
        /// <returns> 1 (um): OK. ou -2 (menos dois): Parâmetro Inválido.</returns>
        [DllImport("MP2032.dll")]
        public static extern int HabilitaEsperaImpressao(int habilitado);

        /// <summary>
        /// Esta função tem por objetivo retornar o estado da impressora. Estes estados são definidos como: ON-LINE, OFF-LINE, Desligada ou Sem Papel.
        /// </summary>
        /// Retorno: 
        /// 0 - Erro de comunicação
        /// 5 - Impressora com pouco papel
        /// 9 - Tampa aberta
        /// 24- Impressora "ONLINE"
        /// 32- Impressora sem papel
        [DllImport("MP2032.dll")]
        public static extern int Le_Status();

        /// <summary>
        /// Reset a impressora
        /// </summary>
        /// <returns> 0 (zero): Erro de Comunicação ou 1 (um): OK.</returns>
        [DllImport("MP2032.dll")]
        public static extern int PrinterReset();

        /// <summary>
        /// Verifica se há papel posicionado no Presenter.
        /// </summary>
        /// <returns>
        /// -1 (menos um): Erro de execução da função.
        /// 0 (zero): Problemas da verificação do papel no presenter.
        /// 1 (um): Papel posicionado no presenter.
        /// 2 (dois): Papel não posicionado no presenter.
        /// 3 (três): Erro desconhecido.
        /// </returns>
        [DllImport("MP2032.dll")]
        public static extern int VerificaPapelPresenter();

        #endregion

        public void imprimir(string text)
        {
            int retorno;

            try
            {
                BPConfiguracao processConfig = new BPConfiguracao();
                BEConfiguracao config = processConfig.ObterTodos(new FEConfiguracao()).First();

                string porta = config.Porta;

                retorno = ConfiguraModeloImpressora(7);
                validaRetorno(retorno, "Configurar Modelo Impressora");

                retorno = IniciaPorta(porta);
                validaRetorno(retorno, "Iniciar Porta");

                retorno = BematechTX(text);
                validaRetorno(retorno, "Imprimir");

                retorno = AcionaGuilhotina(0);
                validaRetorno(retorno, "Acionar Guilhotina");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void validaRetorno(int retorno, string nomeFuncao)
        {
            if (retorno != 1)
                throw new Exception("Não foi possível fazer uma conexão com a impressora. Verifique se a mesma está ligada e se os cabos estão conectados.");
        }

        private void imprimirAntigo(string text)
        {
            ////tamanho do caracter
            //TextoFormatado.TamanhoCaracter tamanhoCaracter;
            //tamanhoCaracter = TextoFormatado.TamanhoCaracter.Normal;

            //// formato do caracter
            //TextoFormatado.FormatoCaracter formato = TextoFormatado.FormatoCaracter.Normal;

            //// alinhamento do texto
            //TextoFormatado.TipoAlinhamento alinhamento;
            //alinhamento = TextoFormatado.TipoAlinhamento.SemAlinhamento;

            //TextoFormatado texto = new TextoFormatado(text + "\r\n", tamanhoCaracter, formato, alinhamento);
            //texto.TabelaCaracteres = miniPrinter.TabelaCaracteres;

            //PortaSerial porta = new PortaSerial();
            //porta.Open("COM8");

            //miniPrinter.Imprimir(texto.ToString());
        }
    }
}
